/*
 * Copyright (c) 2018, apexes.net. All rights reserved.
 *
 *         http://www.apexes.net
 *
 */
package net.apexes.vertx;

import io.vertx.core.AsyncResult;
import io.vertx.core.DeploymentOptions;
import io.vertx.core.Handler;
import io.vertx.core.Verticle;
import io.vertx.core.Vertx;
import io.vertx.core.eventbus.impl.clustered.ClusteredEventBus;
import io.vertx.core.eventbus.impl.clustered.ConnectionMap;

import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.util.function.Supplier;

/**
 * @author <a href=mailto:hedyn@foxmail.com>HeDYn</a>
 */
public class VertxClustered {

    private final Vertx vertx;
    private final GuiceVerticleFactory factory;

    VertxClustered(Vertx vertx, GuiceVerticleFactory factory, ClusteredMessageLogger logger) {
        this.vertx = vertx;
        this.factory = factory;
        if (factory != null) {
            vertx.registerVerticleFactory(factory);
        }
        if (logger != null) {
            try {
                Field connectionsField = ClusteredEventBus.class.getDeclaredField("connections");

                Field modifiersField = Field.class.getDeclaredField("modifiers");
                modifiersField.setAccessible(true);
                modifiersField.setInt(connectionsField, connectionsField.getModifiers() & ~Modifier.FINAL);

                ClusteredEventBus eventBus = (ClusteredEventBus) vertx.eventBus();
                connectionsField.setAccessible(true);
                connectionsField.set(eventBus, new ConnectionMap(eventBus, logger));
            } catch (Exception e) {
                throw new RuntimeException(e);
            }
        }
    }

    public Vertx getVertx() {
        return vertx;
    }

    public GuiceVerticleFactory getFactory() {
        return factory;
    }

    public void deploy(Deployment deployment) {
        deploy(deployment, null);
    }

    public void deploy(Deployment deployment, Handler<AsyncResult<String>> completionHandler) {
        if (factory != null) {
            deployment.deploy(factory.prefix(), vertx, completionHandler);
        } else {
            deployment.deploy(vertx, completionHandler);
        }
    }

    public void deployVerticle(Verticle verticle) {
        vertx.deployVerticle(verticle);
    }

    public void deployVerticle(Verticle verticle, Handler<AsyncResult<String>> completionHandler) {
        vertx.deployVerticle(verticle, completionHandler);
    }

    public void deployVerticle(Verticle verticle, DeploymentOptions options) {
        vertx.deployVerticle(verticle, options);
    }

    public void deployVerticle(Verticle verticle,
                               DeploymentOptions options,
                               Handler<AsyncResult<String>> completionHandler) {
        vertx.deployVerticle(verticle, options, completionHandler);
    }

    public void deployVerticle(Supplier<Verticle> verticleSupplier, DeploymentOptions options) {
        vertx.deployVerticle(verticleSupplier, options);
    }

    public void deployVerticle(Supplier<Verticle> verticleSupplier,
                               DeploymentOptions options,
                               Handler<AsyncResult<String>> completionHandler) {
        vertx.deployVerticle(verticleSupplier, options, completionHandler);
    }

}
